Skip to content

像函数一样使用 Blocks

前提条件:本指南基于 Blocks 的基本介绍。请确保已先阅读 Blocks 与事件监听布局控制 指南。

介绍

除了作为全栈机器学习演示界面外,Gradio Blocks 应用实际上也可以被当作普通的 Python 函数使用!

这意味着如果您有一个名为 demo 的 Gradio Blocks (或 Interface) 应用,您可以像使用任何普通 Python 函数一样使用它。

例如,执行 output = demo("Hello", "friend") 将在输入 "Hello" 和 "friend" 上运行 demo 中定义的第一个事件,并将结果存储在变量 output 中。

通过将应用程序作为函数使用,您可以实现不同 Gradio 应用之间的无缝组合。下面我们将详细介绍如何实现这一点。

将 Blocks 作为函数使用

假设我们有以下演示应用,它将英文文本翻译成德文:

python
import gradio as gr
from transformers import pipeline

pipe = pipeline("translation", model="t5-base")

def translate(text):
    return pipe(text)[0]["translation_text"]  

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            english = gr.Textbox(label="英文文本")
            translate_btn = gr.Button(value="翻译")
        with gr.Column():
            german = gr.Textbox(label="德文文本")

    translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")
    examples = gr.Examples(examples=["I went to the supermarket yesterday.", "Helen is a good swimmer."],
                           inputs=[english])

demo.launch()

现在,假设您有另一个生成英文文本的应用程序,但您还想生成德文文本。您有两种选择:

  1. 复制上面英文到德文翻译的源代码并粘贴到您的应用程序中。
  2. 在您的应用程序中加载上述英文到德文的翻译应用,并将其作为普通 Python 函数使用。

第一种方法虽然技术上总是可行的,但通常会引入不必要的复杂性和代码重复。

第二种方法允许您借用所需的功能,而不必将两个应用程序紧密耦合在一起。

要实现这一点,您只需要在您的源文件中调用 gr.load 类方法。之后,您就可以像使用普通 Python 函数一样使用翻译应用!

以下代码片段和演示展示了如何使用 gr.load

python
import gradio as gr
from transformers import pipeline

# 加载已部署的英文翻译器应用(也可以是本地应用)
english_translator = gr.load(name="spaces/gradio/english_translator")
# 创建文本生成器
english_generator = pipeline("text-generation", model="distilgpt2")

def generate_text(text):
    # 生成英文文本
    english_text = english_generator(text)[0]["generated_text"]  
    # 使用加载的翻译器应用将英文翻译成德文
    german_text = english_translator(english_text)
    return english_text, german_text

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            seed = gr.Text(label="输入短语")
        with gr.Column():
            english = gr.Text(label="生成的英文文本")
            german = gr.Text(label="生成的德文文本")
    btn = gr.Button("生成")
    btn.click(generate_text, inputs=[seed], outputs=[english, german])
    gr.Examples(["My name is Clara and I am"], inputs=[seed])

demo.launch()

请注意,变量 english_translator 是我们的英文到德文翻译应用,但它在 generate_text 函数中像普通函数一样被调用。

加载本地 Blocks 应用

除了加载已部署在 Hugging Face Spaces 上的应用,您还可以直接在同一个 Python 脚本中加载本地定义的 Blocks 应用:

python
import gradio as gr

# 定义一个简单的翻译应用
def reverse_text(text):
    return text[::-1]

with gr.Blocks() as text_reverser:
    input_text = gr.Textbox(label="输入文本")
    output_text = gr.Textbox(label="反转后的文本")
    reverse_btn = gr.Button("反转")
    reverse_btn.click(reverse_text, inputs=input_text, outputs=output_text)

# 在另一个应用中使用这个 Blocks 应用
def process_text(text):
    # 直接使用 text_reverser 作为函数
    reversed_text = text_reverser(text)
    return f"原文: {text}, 反转后: {reversed_text}"

with gr.Blocks() as demo:
    input_box = gr.Textbox(label="请输入文本")
    output_box = gr.Textbox(label="处理结果")
    process_btn = gr.Button("处理")
    process_btn.click(process_text, inputs=input_box, outputs=output_box)

demo.launch()

控制使用应用中的哪个函数

如果您加载的应用定义了多个函数,您可以使用 fn_indexapi_name 参数来指定要使用的函数。

在我们的英文到德文演示代码中,您会看到以下行:

python
translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")

api_name 在我们的应用中为这个函数提供了一个唯一的名称。您可以使用这个名称来告诉 Gradio 您想要使用上游应用中的哪个函数:

python
english_translator(text, api_name="translate-to-german")

您也可以使用 fn_index 参数。想象一下,如果我们的应用还定义了一个英文到西班牙文的翻译功能。要在我们的文本生成应用中使用它,我们可以使用以下代码:

python
english_translator(text, fn_index=1)

Gradio Spaces 中的函数索引从零开始,因此西班牙语翻译器作为我们应用中的第二个函数,索引为 1。

Gradio 客户端与应用加载

Gradio 还提供了一个客户端 API,可以更灵活地与远程 Gradio 应用交互:

python
import gradio as gr
from gradio.client import Client

# 使用客户端连接到远程应用
client = Client("spaces/gradio/english_translator")

def generate_and_translate(text):
    # 使用客户端调用应用的特定函数
    result = client.predict(text, api_name="translate-to-german")
    return result

with gr.Blocks() as demo:
    input_text = gr.Textbox(label="输入英文")
    output_text = gr.Textbox(label="德文翻译")
    translate_btn = gr.Button("翻译")
    translate_btn.click(generate_and_translate, inputs=input_text, outputs=output_text)

demo.launch()

客户端 API 提供了更多控制选项,如设置超时、处理认证和管理并发请求等。

应用加载的最佳实践

  1. 选择正确的加载方法

    • 对于简单的功能重用,直接使用 Blocks 应用作为函数。
    • 对于远程应用,使用 gr.load() 或客户端 API。
    • 对于需要更多控制的场景,使用 Gradio 客户端。
  2. 错误处理:当使用远程应用时,添加适当的错误处理机制:

    python
    def safe_translate(text):
        try:
            return english_translator(text)
        except Exception as e:
            return f"翻译失败: {str(e)}"
  3. 性能考虑:加载远程应用会增加网络延迟。如果性能关键,考虑在本地复制相关功能。

  4. 版本控制:当依赖远程应用时,确保处理API变化的可能性:

    python
    english_translator = gr.load(
        name="spaces/gradio/english_translator", 
        version="1.0.0"  # 指定版本以确保兼容性
    )

结论

将 Gradio Blocks 应用作为函数使用是一种强大的模式,它可以帮助您组合不同应用之间的功能。任何 Blocks 应用都可以被作为函数使用,但一个特别有效的模式是先 load 托管在 Hugging Face Spaces 上的应用,然后将其作为函数在您自己的应用中使用。您还可以加载托管在 Hugging Face Model Hub 上的模型(参考课程视频中的相关演示)。

这种模块化和可组合的方法可以大大提高开发效率,减少代码重复,并让您的应用更加灵活和可维护。